package xyj.sparrow.scheduler.cron.ops;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import xyj.sparrow.scheduler.cron.Cron;
import xyj.sparrow.scheduler.cron.thread.MonitorThread;
import xyj.sparrow.scheduler.entity.App;
import xyj.sparrow.scheduler.entity.Task;
import xyj.sparrow.scheduler.mapper.AppMapper;
import xyj.sparrow.scheduler.mapper.TaskMapper;
import xyj.sparrow.scheduler.server.ClientManager;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 本地消息不需要进行同步
 *
 * @author 江南小俊
 * @since 2021/6/22
 **/
public class LocalMessageSync implements MessageSync {
    @Resource
    private MonitorThread monitorThread;

    @Resource
    private AppMapper appMapper;
    @Resource
    private TaskMapper taskMapper;

    @Override
    public void removeByTaskIds(List<String> taskIds) {
        monitorThread.removeByTaskIds(taskIds);
    }

    @Override
    public void removeByAppIds(List<String> appIds) {
        monitorThread.removeByAppIds(appIds);
    }

    @Override
    public void addCron(Cron cron) {
        monitorThread.addCron(cron);
    }

    @Override
    public void updateCron(Cron cron) {
        monitorThread.updateCron(cron);
    }

    @Override
    public void batchUpdateCronByAppId(List<String> appIds) {
        List<Cron> cronList = listCronByAppId(appIds);
        if (cronList != null && !cronList.isEmpty()) {
            for (Cron cron : cronList) {
                monitorThread.updateCron(cron);
            }
        }
    }

    @Override
    public void batchUpdateCronByTaskId(List<String> taskIds) {
        List<Cron> cronList = listCronByTaskId(taskIds);
        if (cronList != null && !cronList.isEmpty()) {
            for (Cron cron : cronList) {
                monitorThread.updateCron(cron);
            }
        }
    }

    @Override
    public void runCronByTask(String taskId) {
        Task task = taskMapper.selectById(taskId);
        if (task != null) {
            ClientManager.scheduling(task.getAppId(), taskId, LocalDateTime.now());
        }
    }

    private List<Cron> listCronByTaskId(List<String> taskIds) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_status", "1");
        queryWrapper.in("task_id", taskIds);
        List<Task> tasks = taskMapper.selectList(queryWrapper);
        return tasks.stream().map(task -> new Cron(monitorThread, task)).collect(Collectors.toList());
    }

    private List<Cron> listCronByAppId(List<String> appIds) {
        List<String> enabledAppIds = listEnabledAppIds();
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_status", "1");
        queryWrapper.in("app_id", appIds);
        List<Task> tasks = taskMapper.selectList(queryWrapper);
        tasks = tasks.stream().filter(task -> enabledAppIds.contains(task.getAppId())).collect(Collectors.toList());
        return tasks.stream().map(task -> new Cron(monitorThread, task)).collect(Collectors.toList());
    }

    private List<String> listEnabledAppIds() {
        QueryWrapper<App> appQueryWrapper = new QueryWrapper<>();
        appQueryWrapper.eq("app_status", 1);
        List<App> apps = appMapper.selectList(appQueryWrapper);
        return apps.stream().map(App::getAppId).collect(Collectors.toList());
    }
}
